package com.qa.dom.controller;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.toolkit.StringUtils;
import com.qa.dom.config.shiro.CaptchaException;
import com.qa.dom.config.shiro.UsernamePasswordCaptchaToken;
import com.qa.dom.entity.LoginType;
import com.qa.dom.entity.Notice;
import com.qa.dom.entity.Usertable;
import com.qa.dom.service.IUsertableService;
import com.qa.dom.util.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import net.sf.json.JSONObject;
import org.apache.commons.codec.language.bm.Rule;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Api(description = "Login",tags = {"登录控制器"})
@RestController
public class LoginController extends baseAction {
    public static final String MSG_TEMPLATE_LOGIN_ID = "3059636";

    private static final String USER_LOGIN_TYPE = LoginType.USERTABLE.toString();

    @Resource  private IUsertableService usertableService;
    @Autowired
    StringRedisTemplate stringRedisTemplate;


    /**
     * 短信验证码登录发送验证码
     *
     * @param phone
     * @return
     */
    @GetMapping("/sendLoginCode")
    @ApiOperation(value="获取验证码", notes = "验证码" ,httpMethod="GET")
    @ResponseBody
    public JsonResult sendLoginCode(@ApiParam("手机号") @RequestParam("phone") String phone) {
        if (NTESUtils.sendMsg(phone, MSG_TEMPLATE_LOGIN_ID)) {
            return renderSuccess("发送成功");
        }
        return renderError("发送失败");
    }
    /**  校验验证码   将登录信息存入redis   如果进入创建addid  继续调用 checkregist 校验是否需要注册
     * @Description:
     * @Param: [code, phone]
     * @return: com.qa.dom.util.JsonResult
     * @Author: cxj
     * @Date: 2018/4/26
     */
    @GetMapping("/checkCode")
    @ApiOperation(value = "验证码验证" , notes = "验证"  , httpMethod = "GET")
    @ResponseBody
    public  JsonResult checkCode(@ApiParam("验证码") @RequestParam("code")  String code ,@ApiParam("手机号") @RequestParam("phone") String phone){
        try {
            System.out.println(code+"<<<"+phone);
            JSONObject jsonObject = new JSONObject();
            if (StringUtils.isNotEmpty(code)) {
                if (!NTESUtils.checkMsg(phone, code)) {
                    return renderError("验证码有误,请重新输入!");
                }
            } else {
                return renderError("请输入验证码!");
            }
            EntityWrapper<Usertable> wrapper = new EntityWrapper<>();
            wrapper.eq("phone", phone);
            Usertable us = usertableService.selectOne(wrapper);
            System.out.println(us);
            if (us == null) {
                Usertable user1 = new Usertable();
                user1.setPhone(phone);
                String accid = "q" + DateUtil.getSecond() + user1.getId();
                JSONObject ob = NTESUtils.createAccid(accid, phone, Constants.QA_HEAD);
                if (ob!= null) {
                    user1.setAccid(accid);
                    if (usertableService.insert(user1)) {
                        stringRedisTemplate.opsForValue().set("checkLogin"+MD5.md5(phone), phone);
                        stringRedisTemplate.expire("checkLogin"+phone, 2592000, TimeUnit.MILLISECONDS);
                    }

                    jsonObject.put("yuntoken", ob.optString("token"));
                    jsonObject.put("user",user1);
                    jsonObject.put("accid",accid);

                    return renderSuccess(1, "创建accid成功", 0, jsonObject);
                }
                return renderError(0, "创建addid失败", 0, null);
            }
            JSONObject token = NTESUtils.refreshToken(us.getAccid());
            jsonObject.put("yuntoken",token.optString("token"));
            jsonObject.put("user",us);
            jsonObject.put("accid",us.getAccid());
            return renderSuccess(1,"登录成功!",0,jsonObject);
        } catch (Exception e) {
            e.printStackTrace();
            return renderError("登录失败!");
        }
    }
    /**
     * @Description: 校验是否登录 未登录调用sendLoginCode,  (1) :如果过期 发送验证码重新登录,已经登录调用 checkregist  校验 是否需要注册信息
     * @Param: []
     * @return: com.qa.dom.util.JsonResult
     * @Author: cxj
     * @Date: 2018/4/26
     */
    @RequestMapping("/check")
    @ResponseBody
    @ApiOperation(value = "校验是否登录",notes = "我的消息",httpMethod = "POST")
    public  JsonResult  check (@RequestBody String phone){
        System.out.println("校验是否登录"+phone);
        String s = stringRedisTemplate.opsForValue().get("checkLogin"+MD5.md5(phone));
        System.out.println(s+"<<<<");
        if (StringUtils.isNotEmpty(s)){
            EntityWrapper<Usertable> wrapper = new EntityWrapper<>();
            wrapper.eq("phone",s);

            Usertable us = usertableService.selectOne(wrapper);
            return renderSuccess(1,"已经登录，无需登录",0,us);
        }
        return renderError(0,"账号过期重新登录",0,null);
    }


    /**
    * @Description:  校验是否需要注册 true  调用regist 登陆成功之后必须调用该接口
    * @Param:
    * @return:
    * @Author: cxj
    * @Date: 2018/4/26
    */

    @RequestMapping("/checkRegist")
    @ApiOperation(value = "校验是否需要注册",notes = "消息",httpMethod = "POST")
    public JsonResult checkRegist(@RequestBody String phone){
        System.out.println("校验是否需要注册"+phone);
        EntityWrapper<Usertable> wrapper = new EntityWrapper<>();
        wrapper.eq("phone",phone);
        Usertable usr = usertableService.selectOne(wrapper);
        if (usr==null){
            return  renderError("请填写注册信息!");
        }
        return  renderSuccess("无须重复注册!");
    }
    /**
     * @Description: 登录完成  更新数据信息  数据库存在无须重复注册
     * @Param: [phone, code]
     * @return: com.qa.dom.util.JsonResult
     * @Author: cxj
     * @Date: 2018/4/26
     */
    @ApiOperation(value = "更新数据" , notes = "成功"  , httpMethod = "POST")
    @RequestMapping("/regist")
        @ResponseBody
        public JsonResult regist(@ApiParam("手机号") @RequestParam("phone")  String phone ,@RequestBody String user) throws IOException {
             System.out.println(phone+"<<<"+user);
             user = "{nickname:\""+user+"\"}";
            Usertable usertable1 = com.alibaba.fastjson.JSONObject.parseObject(user, Usertable.class);
            EntityWrapper<Usertable> wrapper = new EntityWrapper<>();
            wrapper.eq("phone",phone);
            Usertable usr = null ;
            usr  =  usertableService.selectOne(wrapper);
            if (usr == null){
                return renderError("该用户不存在，无法修改");
            }
            EntityWrapper<Usertable> wrapper2 = new EntityWrapper<>();

            wrapper2.where("phone",usr.getPhone());
            return  usertableService.update(usertable1,wrapper2)?renderSuccess(1,"操作成功",0,null): renderError(0,"操作失败",0,null);
        }


    /**
     * 短信验证码登录
     * @param phone
     * @param code
     * @return
     */
    @RequestMapping("/tloginByMsg")
    @ApiOperation(value = "短信验证码注册" , notes = "成功"  , httpMethod = "GET")
    @ResponseBody
    public JsonResult tloginByMsg(@ApiParam("验证码") @RequestParam("code")  String code ,@ApiParam("手机号") @RequestParam("phone") String phone) throws IOException {
        System.out.println(code+"短信验证注册"+phone);
        EntityWrapper<Usertable> wrapper = new EntityWrapper<>();
        wrapper.eq("phone", phone);
        Usertable us = usertableService.selectOne(wrapper);
        System.out.println(us+"<<<<<<");
        if (us == null) {
            Usertable user1 = new Usertable();
            user1.setPhone(phone);
            user1.setIsfirst(0); //新建用户有没有登入过
            usertableService.insert(user1);
            user1 = usertableService.selectOne(wrapper);
            if (user1!=null) {
                String accid = "q" + DateUtil.getSecond() + user1.getId();
                JSONObject ob = NTESUtils.createAccid(accid, phone, Constants.QA_HEAD);
                if (ob != null) {
                    user1.setAccid(accid);
                    usertableService.updateById(user1);
                    stringRedisTemplate.opsForValue().set("checkLogin" + MD5.md5(phone), phone);
                    stringRedisTemplate.expire("checkLogin" + phone, 2592000, TimeUnit.MILLISECONDS);
                }
            }
        }
        UsernamePasswordCaptchaToken token = new UsernamePasswordCaptchaToken(phone, "", code, USER_LOGIN_TYPE);
        token.setRememberMe(true);

        Subject subject = SecurityUtils.getSubject();

        try {
            subject.login(token);
        } catch (AuthenticationException e) {
            System.out.println(e);
            String simpleName = e.getClass().getSimpleName();
            if ("CaptchaException".equals(simpleName)) {
                return renderError("验证码有误！");
            }
        }
        boolean authenticated = subject.isAuthenticated();

        if (!authenticated) {
            return renderError("登录失败");
        }

            Session session = subject.getSession();
            Usertable u = getCurrentUser();
            if (StringUtils.isEmpty(u.getAccid())) {
                //若云信账号(t+手机号+id)为空，则创建（学生端创建云信ID（手机号+id）是在CC-录入学生-添加试听那）
                String accid = "q" + DateUtil.getSecond() + u.getId();
               JSONObject ob = NTESUtils.createAccid(accid, phone, Constants.QA_HEAD);
                if (ob != null) {
                    u.setAccid(accid);
                    usertableService.updateById(u);
                    JSONObject msg = new JSONObject();
                    msg.put("msg", Constants.WELCOME_MSG);
                    msg.put("msgtype", Constants.MSGTYPE_TEXT);
                    NTESUtils.sendSysMsg(u.getAccid(), msg.toString(), Constants.MSGTYPE_TEXT);//发送系统消息
                    Map<String, Object> data = new HashMap<>();
                    data.put("accid", u.getAccid());
                    data.put("yuntoken", ob.optString("token"));
                    data.put("userinfor", u);
                    data.put("usertoken", session.getId());


                    //登陆成功后，设置为登陆过
                    alrealyLogin(u.getId());
                    return  renderSuccess(1, "登录成功", data);
                } else {
                    return renderError("云信注册失败");
                }
            }
            JSONObject ob = NTESUtils.refreshToken(u.getAccid());//获取最新的云信token
            if (ob != null) {
                Map<String, Object> data = new HashMap<>();
                data.put("accid", u.getAccid());
                data.put("yuntoken", ob.optString("token"));
                data.put("userinfor", u);
                data.put("usertoken", session.getId());
                alrealyLogin(u.getId());
                return renderSuccess(1, "登录成功", data);
            } else {
                return renderError("云信登录失败");
            }
    }

    //登陆成功后，设置为登陆过 isFirst 为1
    public void alrealyLogin(Integer id){
        Usertable usertable = usertableService.selectById(id);
        usertable.setIsfirst(1);
        usertableService.updateById(usertable);
    }


    /**
     *  用户名密码登录
     * @param phone
     * @param code
     * @return
     */
    @RequestMapping("/login")
    @ApiOperation(value = "手机号登陆" , notes = "成功"  , httpMethod = "GET")
    @ResponseBody
    public JsonResult login(@ApiParam("手机号") @RequestParam("phone") String phone) throws IOException {
        System.out.println("手机号"+phone);
        EntityWrapper<Usertable> wrapper = new EntityWrapper<>();
        wrapper.eq("phone", phone);
        Usertable us = usertableService.selectOne(wrapper);
        System.out.println(us+"<<<<<<");
        if (us == null) {
            return renderError("手机号不存在");
        }
        UsernamePasswordCaptchaToken token = new UsernamePasswordCaptchaToken(phone, "","", USER_LOGIN_TYPE);
        token.setRememberMe(true);

        Subject subject = SecurityUtils.getSubject();

        try {
            subject.login(token);
        } catch (AuthenticationException e) {
            System.out.println(e);
            String simpleName = e.getClass().getSimpleName();
            if ("CaptchaException".equals(simpleName)) {
                return renderError("验证码有误！");
            }
        }
        boolean authenticated = subject.isAuthenticated();

        if (!authenticated) {
            return renderError("登录失败");
        }

        Session session = subject.getSession();
        Usertable u = getCurrentUser();



        //登陆成功后，设置为登陆过
        alrealyLogin(u.getId());
        return  renderSuccess(1, "登录成功", null);
    }



}
